#include "file.h"

#include <fcntl.h>
#include <sys/stat.h>

namespace sfc::fs {

namespace sys {
using Path = str::CStr<MAX_PATH>;
}

auto File::create(Path p) -> File {
  auto opts = OpenOptions{.read = true, .write = true, .create = true};
  return opts.open(p);
}

auto File::open(Path p) -> File {
  auto opts = OpenOptions{.read = true};
  return opts.open(p);
}

auto OpenOptions::access_mode() const -> u32 {
  if (!append) {
    if (read && !write) return O_RDONLY;
    if (!read && write) return O_WRONLY;
    if (read && write) return O_RDWR;
  }
  return (read ? O_RDWR : O_WRONLY) | O_APPEND;
}

auto OpenOptions::create_mode() const -> u32 {
  if (create_new) {
    return O_CREAT | O_EXCL;
  }
  if (!truncate) {
    return create ? O_CREAT : 0;
  }
  return create ? (O_CREAT | O_TRUNC) : O_TRUNC;
}

auto OpenOptions::open(Path path) const -> File {
  const auto flag = O_CLOEXEC | this->access_mode() | this->create_mode();
  const auto mode = DEFFILEMODE;  // 0666

  const auto file = ::open(sys::Path{path}, flag, mode);
  if (file == -1) {
    throw Error::last_os_error();
  }
  return File{io::File{file}};
}

}  // namespace sfc::fs
